package com.hbwxz.lockSupport;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * JUC高级三：LockSupport与线程中断
 *
 * @author shenzw
 * @date 2023/12/18
 */
public class LockSupportDemo {

    private static volatile boolean isStop = false;

    public static void main(String[] args) {
        // LockSupport与线程中断
        // 使用中断标识停止线程
//        waysOne();

        // 通过 AtomicBoolean 实现
//        waysTwo();

        // 使用线程自带的 interrupt()方法来中断线程
        waysThree();
    }

    /**
     * 方式三:通过Thread类自带的中断api方法实现（本章主要内容）
     */
    private static void waysThree() {
        // 线程A
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.interrupted()) {
                    System.out.println(Thread.currentThread().getName() + "is stop，program is over.");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "is running...");
            }
        }, "A");
        t1.start();

        // 主线程休眠 1秒，给线程A时间打印
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 线程B模拟业务执行完了打断线程A
        new Thread(() -> {
            t1.interrupt();
        }, "B").start();
    }

    /**
     * 方式二：通过 AtomicBoolean 实现
     * <p>
     * AtomicBoolean就是原子性的Boolean,因为带有原子性天生就不需要加锁
     */
    private static void waysTwo() {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);

        // 线程A
        new Thread(() -> {
            while (true) {
                if (atomicBoolean.get()) {
                    System.out.println(Thread.currentThread().getName() + "is stop，program is over.");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "is running...");
            }
        }, "A").start();

        // 主线程休眠 1秒，给线程A时间打印
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 线程B模拟业务执行完了更改标志符状态
        new Thread(() -> {
            atomicBoolean.getAndSet(true);
        }, "B").start();

    }


    /**
     * 方式一：通过一个 volatile变量实现
     * <p>
     * 如果一个变量被 volatile关键字修饰，那么这个变量就具备线程之间的可见性，在高并发的情况下通过修改变量状态来决定程序和系统的运行
     */
    private static void waysOne() {
        // 需求：启动两个线程 A 和 B，线程 A 根据状态是否执行业务逻辑还是终止线程，主线程休眠 1秒，给线程A时间来打印数据，线程B更改标志符
        // 预期效果：线程A打印 1秒“is running...”，然后结束
        // 线程A
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println(Thread.currentThread().getName() + "is stop，program is over.");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "is running...");
            }
        }, "A").start();

        // 主线程休眠 1秒，给线程A时间打印
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 线程B模拟业务执行完了更改标志符状态
        new Thread(() -> {
            isStop = true;
        }, "B").start();
    }
}
